package com.luxsoft.siipap.em.replica.importadores.cxc;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.log4j.Logger;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.SqlParameterValue;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.util.Assert;

import com.luxsoft.siipap.cxc.model.Abono;
import com.luxsoft.siipap.cxc.model.Aplicacion;
import com.luxsoft.siipap.cxc.model.AplicacionDeNota;
import com.luxsoft.siipap.cxc.model.AplicacionDePago;
import com.luxsoft.siipap.cxc.model.Cargo;
import com.luxsoft.siipap.em.replica.importadores.ImportError;
import com.luxsoft.siipap.model.Periodo;
import com.luxsoft.siipap.service.ServiceLocator2;

/**
 * Importa las notas de cargo
 * 
 * @author Ruben Cancino Ramos
 *
 */
public class ImportadorDeAplicacionesANotasDeCargo2 implements RowCallbackHandler{
	
	private int total;
	
	private int current;
	
	private Logger logger=Logger.getLogger(getClass());
	
	public ImportadorDeAplicacionesANotasDeCargo2(){
	}
	
	protected void setProgress(int progress){
		System.out.println("Progreso: "+progress);
	}
	
	protected void updateCurrent(){
		current++;		
		if(total!=0){
			int progress=current*100/this.total;			
			setProgress(progress);
		}
	}
	
	public void importar(final Long id){
		String sql="SELECT A.PAGO_ID ,CASE WHEN NOTAPAGO_ID IS NOT NULL THEN 'NOTA' ELSE 'PAGO' END AS TIPO " +
			",'PAGO IMPORTADO:'||SYSDATE AS COMENTARIO,A.FECHA,A.IMPORTE,A.PAGOM_ID AS ABONO_ID,A.NOTA_ID AS CARGO_ID " +
			" ,B.ORIGEN_ID AS ORIGEN ,B.NOTA_ID AS NOTA_ABONO" +
			" FROM SW_PAGOS A join SW_PAGOM B ON(A.PAGOM_ID=B.PAGOM_ID) " +
			" WHERE A.PAGO_ID=? ";
		getOrigenTemplate().query(sql,new Object[]{id}, this);
	}
	
	/**
	 * Importa todas las notas de un periodo para el tipo indicado
	 * 
	 * @param periodo
	 * 
	 */
	public void importar(final Periodo periodo){
		String sql="SELECT A.PAGO_ID ,CASE WHEN NOTAPAGO_ID IS NOT NULL THEN 'NOTA' ELSE 'PAGO' END AS TIPO " +
				",'PAGO IMPORTADO:'||SYSDATE AS COMENTARIO,A.FECHA,A.IMPORTE,A.PAGOM_ID AS ABONO_ID,A.NOTA_ID AS CARGO_ID " +
				" ,B.ORIGEN_ID AS ORIGEN ,B.NOTA_ID AS NOTA_ABONO" +
				" FROM SW_PAGOS A join SW_PAGOM B ON(A.PAGOM_ID=B.PAGOM_ID) " +
				" WHERE A.FECHA BETWEEN ?  AND ? AND A.NOTA_ID IS NOT NULL ";
		Object[] params=new Object[]{
			new SqlParameterValue(Types.DATE,periodo.getFechaInicial())	
			,new SqlParameterValue(Types.DATE,periodo.getFechaFinal())
		};
		
		// Calculamos el total
		
		String csql="SELECT COUNT(A.PAGO_ID)FROM SW_PAGOS A join SW_PAGOM B ON(A.PAGOM_ID=B.PAGOM_ID) " +
		" WHERE A.FECHA BETWEEN ?  AND ? AND A.NOTA_ID IS NOT NULL ";
		int tot=getOrigenTemplate().queryForInt(csql,params);
		setTotal(tot);
		errores.clear();		
		getOrigenTemplate().query(sql, params, this);
	}
	
	
	private Cargo buscarCargo(Long siipapId){
		String hql="from Cargo c where c.siipapWinId=?";
		List<Cargo> data=getHibernate().find(hql, siipapId);
		return data.isEmpty()?null:data.get(0);
		
	}
	
	private Abono buscarAbono(Long siipapId){
		String hql="from Abono c  left join fetch c.aplicaciones ap where c.siipapId=?";
		List<Abono> data=getHibernate().find(hql, siipapId);
		return data.isEmpty()?null:data.get(0);
	}
	
	public Abono importarNota(final Long id){
		return ImportadorDeNotas.getInstance().importar(id);
	}
	public Cargo importarCargo(final Long id){
		return ImportadorDeNotasDeCargo.instance().importar(id);
	}
	
	public Abono importarPago(final Long id){
		return ImportadorDePagos.getInstance().importar(id);
	}
	
	
	public JdbcTemplate getOrigenTemplate(){
		return ServiceLocator2.getAnalisisJdbcTemplate();
	}

	public int getTotal() {
		return total;
	}

	public void setTotal(int total) {
		System.out.println("Total a procesar: "+total);
		this.total = total;
	}
	
	public HibernateTemplate getHibernate(){
		return ServiceLocator2.getHibernateTemplate();
	}	

	public void processRow(ResultSet rs) throws SQLException {
		Long pagoid=rs.getLong("PAGO_ID");
		String tipo=rs.getString("TIPO");
		try {
			
			//Lo primero es localizar el abono
			Long abonoId=rs.getLong("ABONO_ID");		
			Long abonoOrigen=rs.getLong("ORIGEN"); //En casp de disponibles
			if(abonoOrigen>0)
				abonoId=abonoOrigen; //Si existe el origen este es el abono actual
			if("NOTA".equals(tipo))  // Si se trata de un pago con nota el abono es la nota
				abonoId=rs.getLong("NOTA_ABONO");			
			
			// buscamos en MySQL
			Abono abono=buscarAbono(abonoId);
			// Tratamos de importar
			if(abono==null){
				if("NOTA".equals(tipo)){
					abono=importarNota(abonoId); //Si es nota se importa la nota
				}
				else 
					abono=importarPago(abonoId); // si es pago se importa el pago
			}
			
			Assert.notNull(abono,"No localizo o pudo importar el abono: "+abonoId+" tipo:"+tipo);
			
			//Paso 2 Definimos que tipo de aplicacion			
			final Aplicacion a;
			
			if("NOTA".equals(tipo))
				a=new AplicacionDeNota();
			else
				a=new AplicacionDePago();
			
			// Paso 3 Buscamos el cargo
			Long cargoId=rs.getLong("CARGO_ID");
			
			Cargo cargo=buscarCargo(cargoId);
			if(cargo==null){
				cargo=importarCargo(cargoId);
			}
			Assert.notNull(cargo,"No localizo o pudo uimportar la nota de cargo: "+cargoId+" Tipo:"+tipo);
			a.setCargo(cargo);

			// Paso 4 Asignamos valores del ResultSet
			a.setSiipapId(pagoid);
			a.setComentario(rs.getString("COMENTARIO"));		
			a.setFecha(rs.getDate("FECHA"));
			a.setImporte(rs.getBigDecimal("IMPORTE"));
			
			// Paso 5 elminamos y agregamos del abono y persistimos el mismo			
			boolean existia=abono.getAplicaciones().remove(a);
			abono.agregarAplicacion(a);
			a.actualizarDetalle();
			
			if(existia)
				System.out.println("La aplicacion ya existia");
			getHibernate().merge(abono);
		} catch (Exception e) {
			logger.error(e);
			ImportError ie=new ImportError(e,pagoid,"Error Aplicacion a Nota de Cargo desde SW_PAGOS");
			addError(ie);
			System.out.println(ie);
		}finally{
			updateCurrent();
		}
		
	}
	
	public void addError(ImportError err){
		errores.add(err);
	}
	
	public Set<ImportError> errores=new HashSet<ImportError>();
	
    private static ImportadorDeAplicacionesANotasDeCargo2 INSTANCE;
	
	public static ImportadorDeAplicacionesANotasDeCargo2 instance(){
		if(INSTANCE==null){
			INSTANCE=new ImportadorDeAplicacionesANotasDeCargo2();
		}
		return INSTANCE;
	}

	public static void main(String[] args) {
		ImportadorDeAplicacionesANotasDeCargo2 imp=instance();		
		//imp.importar(new Periodo("11/01/2008","11/01/2008"));
		//imp.importar(2706708L);
		Long[] ids={
				/*2741670L, 2730136L, 2725988L, 2735302L, 2741669L, 2726647L,
				2765162L, 2765163L, 2758314L, 2753891L, 2753892L, 2764488L, 2764489L, 2764486L, 2757545L, 2764487L,
				2807422L,2807423L,
				2822969L, 2811694L, 2811693L, 2813945L,
				2895054L, 2895055L, 2893753L, 2895203L, 2871132L, 2900305L, 2895060L, 2895057L, 2869062L, 2895056L, 2895059L, 2895058L,
				2902843L, 2928946L, 2913296L, 2922847L, 2927523L,
				2960353L, 2939411L, 2960352L, 2937951L, 2939413L, 2939412L, 2947960L*/
				2970343L, 2970344L, 2970345L, 2975655L,
				3046277L, 3046279L, 3046278L, 3046280L, 3008394L
				
		};
		for(Long id:ids){
			try {
				imp.importar(id);
			} catch (Exception e) {
				System.out.println(ExceptionUtils.getRootCauseMessage(e));
			}
			
		}
		
	}
	 
}
